home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyo (Python 2.5) from __future__ import with_statement from util.vec import vector from util import linkify import protocols from interfaces import IInfoboxHTMLProvider import sys import wx from wx import RectPS, RectS, Point, CallLater, GetMouseState, FindWindowAtPointer, GetMousePosition, Size, PaintDC, BufferedPaintDC import warnings import wx.html as html from gui.capabilitiesbar import CapabilitiesBar from contacts.Contact import Contact from contacts.metacontacts import MetaContact from common.emailaccount import EmailAccount from social.network import SocialNetwork from gui import skin from gui.skin.skinobjects import SkinColor, Margins from gui.infobox.emailpanels import EmailList, Header from common import pref, setpref, profile from gui.buddylist import BuddyList from gui.windowfx import fadein from gui.toolbox import CopyToClipboard from gui.textutil import CopyFont, TagFont, default_font from util import Storage, Point2HTMLSize from gui.infobox.errorpanel import ErrorPanel from cgui import SimplePanel from gui.windowfx import ApplySmokeAndMirrors from common import prefprop from gui.toolbox import Monitor from gui import imwin from cgui import SplitImage4 import wx.lib.wxpTag as wx from gui.windowfx import move_smoothly, resize_smoothly from gui.infobox.htmlgeneration import GetInfo from logging import getLogger log = getLogger('infobox') from common import bind import traceback from traceback import print_exc DEFAULT_INFOBOX_WIDTH = 330 TRAY_TIMER_MS = 500 from threading import currentThread class ExpandoPanel(wx.Panel): def __init__(self, parent, infobox): wx.Panel.__init__(self, parent, pos = (-300, -300)) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.SetMinSize(wx.Size(20, 20)) self.infobox = infobox Bind = self.Bind Bind(wx.EVT_PAINT, self.OnPaint) Bind(wx.EVT_LEFT_UP, self.OnLUp) Bind(wx.EVT_LEFT_DCLICK, self.OnDClick) Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter) Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) def OnMouseEnter(self, event): if not self.HasCapture(): self.CaptureMouse() self.Refresh(False) def OnMouseLeave(self, event): while self.HasCapture(): self.ReleaseMouse() self.Refresh(False) def OnPaint(self, event): dc = BufferedPaintDC(self) infobox = self.infobox contact = infobox.metacontact[infobox.expandopanels.index(self)] rect = RectS(self.Size) iconsize = 16 padx = infobox.padding.x i = None if infobox.account == contact else self.HasCapture() infobox.contactbg[i].Draw(dc, rect) dc.SetFont(infobox.headerfont) dc.SetTextForeground(infobox.contactfontcolor[i]) name = contact.alias servico = contact.serviceicon.Resized(iconsize) statico = skin.get('statusicons.' + contact.status_orb).ResizedSmaller(iconsize) dc.DrawBitmap(servico, 2 + padx, 2, True) dc.DrawText(name, 21 + padx, 2) dc.DrawBitmap(statico, (rect.width - 18) + (16 - statico.Size.width) // 2 - padx, rect.height // 2 - statico.Height // 2) def OnDClick(self, event): infobox = self.infobox contact = infobox.metacontact[infobox.expandopanels.index(self)] infobox.Hide() imwin.begin_conversation(contact) def OnLUp(self, event): infobox = self.infobox contact = infobox.metacontact[infobox.expandopanels.index(self)] if self.HasCapture() and contact is not infobox.account: infobox.SelectContact(contact) infobox.cpanel.Refresh(False) class InfoBoxShowingTimer(wx.Timer): def __init__(self, infobox): self.infobox = infobox wx.Timer.__init__(self) def Start(self, contact): self.contact = contact wx.Timer.Start(self, pref('infobox.show_delay', 1000), True) def Notify(self): i = self.infobox if i is None or wx.IsDestroyed(i): print >>sys.stderr, 'Infobox is dead but still getting notified!' return None if i.FriendlyTouch(): i.ShowOnScreen() i.InfoSync() i.quickshow = True class InfoBoxHidingTimer(wx.Timer): def __init__(self, infobox): self.infobox = infobox wx.Timer.__init__(self) def Notify(self): i = self.infobox if i is None or wx.IsDestroyed(i): return None i.mouseouttimer.Stop() i.showingtimer.Stop() i.quickshow = False i.Hide() class InfoBoxTrayTimer(wx.Timer): def __init__(self, infobox): wx.Timer.__init__(self) self.infobox = infobox def Notify(self): try: mp = GetMousePosition() except Exception: return None import cgui tray_rect = cgui.GetTrayRect() i = self.infobox if i is None or wx.IsDestroyed(i): return None infobox_rect = i.Rect.Inflate(30, 30) if not infobox_rect.Contains(mp) and not tray_rect.Contains(mp): i.Hide() self.Stop() class InfoBoxMouseOutTimer(wx.Timer): def __init__(self, infobox): self.infobox = infobox wx.Timer.__init__(self) self.hider = InfoBoxHidingTimer(infobox) self.noneweredown = False def Start(self): wx.Timer.Start(self, 200) self.delayhide = False def Notify(self): try: mp = GetMousePosition() except: return None ms = GetMouseState() if not ms.LeftDown() and ms.RightDown(): pass button_down = ms.MiddleDown() infobox = self.infobox infobox_rect = infobox.Rect inside = infobox_rect.Contains(mp) ftouch = infobox.FriendlyTouch(mp) if inside: self.delayhide = True elif ftouch: self.delayhide = False hider = self.hider if not inside and ftouch and infobox.capbar.cbar.overflowmenu.IsShown() and infobox.capbar.cto.menu.IsShown(): pass if not infobox.capbar.cfrom.menu.IsShown() and self.noneweredown: if button_down: hider.Start(1, True) if not hider.IsRunning(): wap = wx.FindWindowAtPoint(mp) if wap is not None: if infobox.Parent.Top is wap.Top: pass inancestor = wap.Top is not wap else: inancestor = False None(hider.Start if self.delayhide or inancestor else 1, True) else: self.noneweredown = False if hider.IsRunning(): hider.Stop() self.noneweredown = not button_down class InfoBox(wx.Frame): def __dtor__(self): for attr in ('mouseouttimer', 'showingtimer', 'hidingtimer', 'traytimer'): obj = getattr(self, attr, None) if obj is not None: obj.infobox = None obj.Stop() continue def __init__(self, parent): wx.Frame.__init__(self, parent, -1, '', style = wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP | wx.NO_BORDER | wx.FRAME_TOOL_WINDOW) self._cache = { } self.friends = set() self.quickshow = False self.metacontact = None self.account = None self._doubleclickhide = False self.expandopanels = [] self.mouseouttimer = InfoBoxMouseOutTimer(self) self.showingtimer = InfoBoxShowingTimer(self) self.hidingtimer = None self.traytimer = InfoBoxTrayTimer(self) timers = [ self.mouseouttimer, self.showingtimer, self.hidingtimer] None((self.Bind, wx.EVT_WINDOW_DESTROY), (lambda e: [] if e.EventObject is self else None)) self.animationtimer = None self.load_format() self.pl = 0 self.pr = 0 self.force_corner = False self.Show(False) panel = self.panel = wx.Panel(self, pos = (-400, -400)) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.UpdateSkin() self.content = wx.BoxSizer(wx.VERTICAL) sizer = panel.Sizer = wx.GridBagSizer() sizer.SetEmptyCellSize(wx.Size(0, 0)) sizer.AddGrowableCol(1, 1) sizer.AddGrowableRow(1, 1) sizer.Add(self.content, (1, 1), flag = wx.EXPAND) sizer.Add(wx.Size(self.framesize.left, self.framesize.top), (0, 0)) sizer.Add(wx.Size(self.framesize.right, self.framesize.bottom), (2, 2)) caps = self.capbar = CapabilitiesBar((self.panel,), (lambda : self.account), True, True) for b in ('info', 'im', 'email', 'sms'): caps.GetButton(b).Bind(wx.EVT_BUTTON, (lambda e, b = (b,): (self.Hide(), wx.CallAfter(self.account.imwin_mode, b)))) import gui.pref.prefsdialog as gui (caps.OnSendFiles,) += (lambda : (self.Hide(), self.account.send_file())) (caps.OnSendFolder,) += (lambda : (self.Hide(), self.account.send_folder())) (caps.OnViewPastChats,) += (lambda : (self.Hide(), self.account.view_past_chats())) (caps, caps.OnAlert) += (lambda : (self.Hide(), gui.pref.prefsdialog.show('notifications'))) wx.CallAfter(caps.ShowToFrom, False) wx.CallAfter(caps.ShowCapabilities, pref('infobox.showcapabilities', True)) self.content.Add(self.capbar, 0, wx.EXPAND) self.eheader = Header(panel) self.content.Add(self.eheader, 0, wx.EXPAND) self.eheader.Show(False) self.cpanel = wx.Panel(panel) self.cpanel.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.cpanel.Sizer = wx.BoxSizer(wx.VERTICAL) self.content.Add(self.cpanel, 1, wx.EXPAND) self.elist = EmailList(panel) self.content.Add(self.elist, 1, wx.EXPAND) self.elist.Show(False) self.errorpanel = ErrorPanel(panel) self.content.Add(self.errorpanel, 1, wx.EXPAND) self.errorpanel.Show(False) panel.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) panel.Bind(wx.EVT_PAINT, self.OnPaint) panel.Bind(wx.EVT_ERASE_BACKGROUND, (lambda e: pass)) panel.SetSize(wx.Size(DEFAULT_INFOBOX_WIDTH, DEFAULT_INFOBOX_WIDTH)) pbox.SetMaxWordLength(self.width - 85) pbox.SetBorders(self.padding.x) self.Bind(wx.EVT_SIZE, self.OnSize) def set_fonts(val): self.profilebox.SetFonts(pref('infobox.fonts.normal', default_font().FaceName), pref('infobox.fonts.fixed', 'Courier New')) profile.prefs.link('infobox.fonts.normal', set_fonts, callnow = False, obj = self) profile.prefs.link('infobox.fonts.fixed', set_fonts, obj = self) self.profilebox.Bind(html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked) self.cpanel.Sizer.Add(self.profilebox, 1, wx.EXPAND) wx.CallAfter(self.DoSizeMagic) def CtrlCHandler(self): CopyToClipboard(self.profilebox.SelectionToText()) CtrlCHandler = bind('InfoBox.Copy')(CtrlCHandler) def do_focus(self): for ctrl in (self.profilebox, self.elist, self.cpanel): if ctrl.IsShownOnScreen(): print 'focusing', ctrl self.ReallyRaise() ctrl.SetFocusFromKbd() break continue def load_format(self): import syck try: try: f = _[2] self.format = dict(syck.load(f)) finally: pass except: self.format = { } print_exc() def UpdateSkin(self): s = skin.get self.framesize = s('infobox.framesize', (lambda : Margins([ 0, 0, 0, 0]))) self.padding = s('infobox.padding', (lambda : Point(2, 2))) if hasattr(self, 'profilebox'): self.profilebox.SetBorders(self.padding.x) self.headerfont = s('infobox.fonts.header', default_font) self.headerfc = s('infobox.fontcolors.header', wx.BLACK) self.headerhoverfc = s('infobox.fontcolors.contacthover', wx.BLACK) self.headerselfc = s('infobox.fontcolors.contactselected', wx.BLACK) titlefont = skin.get('infobox.fonts.title', default_font) majorfont = skin.get('infobox.fonts.major', default_font) minorfont = skin.get('infobox.fonts.minor', default_font) linkfont = CopyFont(skin.get('infobox.fonts.link', default_font), underline = True) h = self.htmlfonts = Storage() h.header = self.headerfont h.title = titlefont h.major = majorfont h.minor = minorfont h.link = linkfont h.headerfont = self.headerfont.FaceName h.titlefont = titlefont.FaceName h.majorfont = majorfont.FaceName h.minorfont = minorfont.FaceName h.linkfont = linkfont.FaceName h.headersize = Point2HTMLSize(self.headerfont.PointSize) h.titlesize = Point2HTMLSize(titlefont.PointSize) h.majorsize = Point2HTMLSize(majorfont.PointSize) h.minorsize = Point2HTMLSize(minorfont.PointSize) h.linksize = Point2HTMLSize(linkfont.PointSize) h.headerfc = self.headerfc.GetAsString(wx.C2S_HTML_SYNTAX) h.titlefc = s('infobox.fontcolors.title', wx.BLACK).GetAsString(wx.C2S_HTML_SYNTAX) h.majorfc = s('infobox.fontcolors.major', wx.BLACK).GetAsString(wx.C2S_HTML_SYNTAX) h.minorfc = s('infobox.fontcolors.minor', (lambda : wx.Color(128, 128, 128))).GetAsString(wx.C2S_HTML_SYNTAX) h.linkfc = s('infobox.fontcolors.link', wx.BLUE).GetAsString(wx.C2S_HTML_SYNTAX) self.bg = s('infobox.frame', (lambda : SkinColor(wx.BLACK))) self.barskin = s('capabilitiesbar', None) self.contactbg = [ s('infobox.backgrounds.contact', (lambda : SkinColor(wx.Colour(128, 128, 128)))), s('infobox.backgrounds.contacthover', (lambda : SkinColor(wx.GREEN))), s('infobox.backgrounds.contactselected', (lambda : SkinColor(wx.WHITE)))] self.contactfontcolor = [ s('infobox.fontcolors.contact', wx.BLACK), s('infobox.fontcolors.contacthover', wx.BLACK), s('infobox.fontcolors.contactselected', wx.BLACK)] s = self.panel.Sizer if s: s.Detach(1) s.Detach(1) s.Add(wx.Size(self.framesize.left, self.framesize.top), (0, 0)) s.Add(wx.Size(self.framesize.right, self.framesize.bottom), (2, 2)) if hasattr(self, 'capbar') and hasattr(self, 'cpanel'): sizer = self.content sizer.Detach(self.capbar) sizer.Detach(self.cpanel) sizer.Add(self.capbar, 0, wx.EXPAND) sizer.Add(self.cpanel, 1, wx.EXPAND) self._cache.clear() def OnPaint(self, event): self.bg.Draw(PaintDC(self.panel), RectS(self.panel.Size)) def DoSizeMagic(self): width = self.width filled = sum((lambda .0: for panel in .0: panel.Size.height)(self.expandopanels)) if self.capbar.Shown: filled += self.capbar.Size.height if self.eheader.Shown: filled += self.eheader.Size.height maxheight = Monitor.GetFromWindow(wx.FindWindowByName('Buddy List')).ClientArea.height * pref('infobox.ratio_to_screen', 0.75) if self.elist.Shown: content = self.elist desired = content.GetFullHeight() elif self.cpanel.Shown: content = self.profilebox content.SetSize(wx.Size(width, 1)) desired = content.VirtualSize.height + 16 elif self.errorpanel.Show: content = self.errorpanel desired = content.MinSize.height allotted = min(desired + filled, maxheight) if getattr(self.account, 'service', None) == 'twitter': allotted = maxheight contentsize = None if isinstance(content, EmailList) and allotted == maxheight else allotted - filled content.SetSize(wx.Size(width, contentsize)) sz = Size(width + self.framesize.left + self.framesize.right, contentsize + filled + self.framesize.top + self.framesize.bottom) if getattr(self, '_resizingto', None) != sz and pref('infobox.animation.resizing', False): resize_smoothly(self, sz) self._resizingto = sz else: self.Size = sz self.panel.SetSize(sz) wx.CallAfter(self.panel.Layout) wx.CallAfter(self.cpanel.Layout) if hasattr(self, 'bg') and isinstance(self.bg, SplitImage4): ApplySmokeAndMirrors(self, self.bg.GetBitmap(self.Size)) else: ApplySmokeAndMirrors(self) def DelayedHide(self): if not self.hidingtimer: self.hidingtimer = CallLater(1000, self.DoDelayedHide) def DoDelayedHide(self): self.hidingtimer = None if not self.Rect.Contains(GetMousePosition()): self.Hide() def Hide(self): if self.hidingtimer: self.hidingtimer.Stop() self.hidingtimer = None if self.showingtimer.IsRunning(): self.showingtimer.Stop() if self.traytimer.IsRunning(): self.traytimer.Stop() self.Show(False) def DoubleclickHide(self): self._doubleclickhide = True self.Hide() def InvalidateDoubleclickHide(self): self._doubleclickhide = False def DrawCrap(self, c1, c2, mp): tan = tan radians = radians import math DX = abs(c1.x - mp.x) LA = self.min_angle_of_entry HA = self.max_angle_of_entry minDY = int(abs(tan(radians(LA)) * DX)) maxDY = int(abs(tan(radians(HA)) * DX)) DY1 = min(max(abs(c1.y - mp.y), minDY), maxDY) DY2 = min(max(abs(c2.y - mp.y), minDY), maxDY) AP1 = Point(c1.x, mp.y - DY1) AP2 = Point(c1.x, mp.y + DY2) sdc = wx.ScreenDC() sdc.SetBrush(wx.Brush(wx.Color(0, 255, 0, 125))) sdc.SetPen(wx.Pen(wx.Color(0, 0, 255, 255))) sdc.DrawPolygon((AP1, AP2, mp)) sdc.Pen = wx.RED_PEN sdc.DrawLinePoint(mp, c1) sdc.DrawLinePoint(mp, c2) def StateChanged(self, *a): wx.CallAfter(self._StateChanged, *a) def _StateChanged(self, *a): account = self.account online = account.state in (account.Statuses.ONLINE, account.Statuses.CHECKING) issocnet = isinstance(account, SocialNetwork) isemail = isinstance(account, EmailAccount) self.capbar.Show(False) if issocnet: pass self.cpanel.Show(online) self.eheader.SetAccount(account) self.eheader.Show(True) if isemail and online: self.elist.SetAccount(account) else: self.elist.Show(False) if issocnet and online and account.dirty: self.InfoSync() if account.state == account.Statuses.OFFLINE: pass active = account.offline_reason == account.Reasons.WILL_RECONNECT if active: message = lambda : profile.account_manager.state_desc(account) elif not online or profile.account_manager.state_desc(account): pass message = None error_link = account.error_link() if error_link is None: self.errorpanel.Error(message) else: (link, cb) = error_link self.errorpanel.Error(message, link, cb) def BuddyListItem(self): return None if self.metacontact else self.account BuddyListItem = property(BuddyListItem) def SelectNext(self): mc = self.metacontact if mc: i = mc.index(self.account) + 1 l = len(mc) if i >= l: i -= l self.SelectContact(mc[i]) for panel in self.expandopanels: panel.Refresh() def SelectLast(self): mc = self.metacontact if mc: i = mc.index(self.account) - 1 self.SelectContact(mc[i]) for panel in self.expandopanels: panel.Refresh() def MetaContactObserver(self, obj, attr, old, new): wx.CallAfter(self._MetaContactObserver, obj, attr, old, new) def _MetaContactObserver(self, obj, attr, old, new): if wx.IsDestroyed(self): warnings.warn('Infobox is dead but is still getting notified from MetaContactOberver') return None if self.account not in self.metacontact or not (self.Shown): try: self.account = self.metacontact.first_online except AttributeError: err = ''.join([ 'The obj: ', str(obj), '\nThe attr: ', attr, '\nold -> new: ', str(old), '->', str(new), '\n\nThe Metacontact: ', str(self.metacontact)]) log.error(err) except: None<EXCEPTION MATCH>AttributeError None<EXCEPTION MATCH>AttributeError self.Repanelmater() self.Reposition() def ContactObserver(self, obj, attr, old, new): wx.CallAfter(self._ContactObserver, obj, attr, old, new) def _ContactObserver(self, obj, attr, old, new): self.InfoSync() for panel in self.expandopanels: panel.Refresh() def Display(self, pl, pr, caller, force_corner = False, force_change = False): try: self.hidingtimer.Stop() self.hidingtimer = None except AttributeError: pass if self._doubleclickhide and caller is self.BuddyListItem: return None if not pl == self.pl and pr == self.pr and caller is self.metacontact or caller is self.account: if hasattr(self, 'pausedover'): self.pausedover.Stop() mp = GetMousePosition() rect = self.Rect onleft = rect.x < mp.x if self.Shown: if not force_change: pass if not force_corner: lp = getattr(self, 'LastMousePoint', mp) dp = mp - lp lmd = getattr(self, 'LastMouseDirection', [ False, False]) d = self.LastMouseDirection = (None, None if dp.x else lmd[0] if dp.y else lmd[1]) c1 = rect.Position c2 = c1 + wx.Point(0, rect.height) if pref('infobox.tracelines', False): self.DrawCrap(c1, c2, mp) if (d[0] or not onleft or not d[0]) and onleft: c = None if d[1] else c1 am = (vector(*lp) - vector(*mp)).angle ac = max(min((vector(*lp) - vector(*c)).angle, self.max_angle_of_entry), self.min_angle_of_entry) if am < ac and mp.y > c1.y and mp.y < c2.y: self.LastMousePoint = None + mp if onleft else (-1, 0) self.pausedover = None((None, None, None, CallLater, self.pause_time), (lambda : None if self.FriendlyTouch(mp) else None)) return None self.LastMousePoint = None + mp(*wx.Point if onleft else (-1, 0)) if isinstance(self.account, SocialNetwork): self.errorpanel.Error() try: self.account.unobserve_count(self.InfoSync) except NotImplementedError: pass try: n = self.account.remove_observer(self.StateChanged, 'state') except NotImplementedError: pass except: None<EXCEPTION MATCH>NotImplementedError None<EXCEPTION MATCH>NotImplementedError if isinstance(self.account, EmailAccount): self.errorpanel.Error() n = self.account.remove_observer(self.StateChanged, 'state') elif isinstance(self.account, Contact): if self.metacontact: if hasattr(self, 'metacontact_observer'): self.metacontact_observer.disconnect() del self.metacontact_observer else: log.warning("unobserving a MetaContact, but didn't have a metacontact_observer") else: n = self.account.remove_observer(self.ContactObserver, 'status', 'status_message', 'idle', 'icon') self.pl = pl self.pr = pr if force_corner != self.force_corner: self.Show(False) self.force_corner = force_corner if isinstance(caller, (Contact, MetaContact)): self.eheader.Show(False) self.elist.Show(False) self.capbar.Show(True) self.cpanel.Show(True) if isinstance(caller, MetaContact): metacontact = caller contact = caller.first_online else: metacontact = [] contact = caller if not self.IsShown() and metacontact != self.metacontact or contact is not self.account: if metacontact: pass elif True: self.metacontact = metacontact self.account = contact if metacontact: self.metacontact_observer = metacontact.add_list_observer(self.MetaContactObserver, self.ContactObserver, 'status', 'status_message', 'idle', 'icon') else: contact.add_observer(self.ContactObserver, 'status', 'status_message', 'idle', 'icon') if self.account is not None: caps = self.capbar if isinstance(self.account, MetaContact): buddies = self.account name = buddies.alias else: buddies = [ self.account] name = self.account.name if any((lambda .0: for b in .0: b.blocked)(buddies)): content = _('Unblock %s') else: content = _('Block %s') caps.iblock.content = [ content % name] elif isinstance(caller, EmailAccount): self.metacontact = [] self.account = caller self.account.add_observer(self.StateChanged, 'state') self._StateChanged() elif isinstance(caller, SocialNetwork): self.metacontact = [] self.account = caller try: self.account.observe_count(self.InfoSync) except NotImplementedError: pass try: self.account.add_observer(self.StateChanged, 'state') except NotImplementedError: pass self._StateChanged() self.Repanelmater() self.Reposition() if not self.IsShown(): if force_corner: fadein(self, 'xfast') self.traytimer.Start(TRAY_TIMER_MS) elif self.quickshow: self.ShowOnScreen() elif not self.showingtimer.IsRunning() or self.account is not self.showingtimer.contact: self.showingtimer.Start(self.account) if not force_corner and not self.mouseouttimer.IsRunning(): self.mouseouttimer.Start() def ShowOnScreen(self): self.ShowNoActivate(True) if 'wxMSW' in wx.PlatformInfo: show_on_top(self) def OnSize(self, event): event.Skip() if self.pl and self.pr: if self.ScreenRect.Contains(wx.GetMousePosition()): wx.CallLater(250, self.Reposition) else: self.Reposition() self.Refresh() def Reposition(self): pl = self.pl pr = self.pr force_corner = self.force_corner size = self.Size if not force_corner: p1 = None if self.right_of_list else pr p2 = None if self.right_of_list else (pl[0] - self.Size.width, pl[1]) p2rect = RectPS(wx.Point(*p2), wx.Size(*size)) screenrect = None(Monitor.GetFromRect(RectPS if self.right_of_list else pl, size)).ClientArea offscreen = None if self.right_of_list else p2rect.left < screenrect.left pos = None if offscreen else p2 direction = wx.TOP | wx.BOTTOM else: pos = (force_corner - Point(*size)) + Point(1, 1) direction = wx.TOP | wx.BOTTOM | wx.LEFT | wx.RIGHT r = wx.RectPS(wx.Point(*pos), wx.Size(*size)) screenrect = Monitor.GetFromRect(r).ClientArea pos = screenrect.Clamp(r, direction).Position if not force_corner and self.animate and self.Shown: if self.animation_method == 2: if getattr(self, '_moving_to', None) != pos: self.animationtimer = move_smoothly(self, pos, time = self.animation_time, interval = self.animation_interval) else: self.animationtimer = self.SlideTo(pos) elif self.animationtimer: self.animationtimer.stop() self.animationtimer = None self.SetPosition(pos) if force_corner: self.traytimer.Start(TRAY_TIMER_MS) self._moving_to = pos animation_time = prefprop('infobox.animation.time', 200) animation_interval = prefprop('infobox.animation.interval', 10) animation_method = prefprop('infobox.animation.method', 1) animate = prefprop('infobox.animate', False) right_of_list = prefprop('infobox.right_of_list', True) max_angle_of_entry = prefprop('infobox.max_angle_of_entry', 60) min_angle_of_entry = prefprop('infobox.max_angle_of_entry', 30) pause_time = prefprop('infobox.pause_time', 250) width = prefprop('infobox.width', DEFAULT_INFOBOX_WIDTH) def on_synctimer(self): t = self.synctimer t.Stop() if t.needs_sync: t.needs_sync = False self.InfoSync() def InfoSync(self, *a): if not hasattr(self, 'synctimer'): self.synctimer = wx.PyTimer(self.on_synctimer) self.synctimer.needs_sync = False if self.synctimer.IsRunning(): self.synctimer.needs_sync = True return None pb = self.profilebox cpanel = self.cpanel self.Frozen().__enter__() try: if cpanel.IsShown(): if self.capbar.Shown: self.capbar.ApplyCaps(self.account) try: pfile = self.FillInProfile() except Exception: traceback.print_exc() pfile = _(u'Error generating content') pb._page = pfile pb.GetPage = lambda : pb._page pb.SetPage(pfile) self.DoSizeMagic() finally: pass self.synctimer.StartOneShot(300) def Repanelmater(self): panelsneeded = len(self.metacontact) exp = self.expandopanels sz = self.cpanel.Sizer if panelsneeded > 0: while len(exp) < panelsneeded: panel = ExpandoPanel(self.cpanel, self) exp.insert(0, panel) sz.Insert(0, panel, 0, wx.EXPAND) while len(exp) > panelsneeded: panel = exp[0] panel.Show(False) exp.remove(panel) sz.Detach(panel) panel.Destroy() else: for panel in exp[:]: panel.Show(False) exp.remove(panel) sz.Detach(panel) panel.Destroy() self.cpanel.Refresh() self.InfoSync() def SelectContact(self, contact): self.account = contact self.InfoSync() def FillInProfile(self): acct = self.account try: ibp = IInfoboxHTMLProvider(acct) except protocols.AdaptationFailure: pass if ibp._dirty or acct not in self._cache: self._cache[acct] = ibp.get_html(self.htmlfonts) return self._cache[acct] if isinstance(acct, SocialNetwork): cachekey = acct if getattr(acct, 'header_tabs', False): currtab = acct._current_tab cachekey = (acct, currtab) dirty = acct._dirty[currtab] elif getattr(acct, '_dirty', False): cachekey = acct dirty = True else: dirty = False if dirty or cachekey not in self._cache: print 'Regenerating profile for %r' % acct self._cache[cachekey] = linkify(self.make_format(cachekey)) if getattr(acct, 'header_tabs', False): acct._dirty[cachekey[1]] = False else: acct._dirty = False self._cache[cachekey] = ''.join((lambda .0: for y in .0: y.strip())(self._cache[cachekey].split('\n'))) return self._cache[cachekey] elif isinstance(acct, EmailAccount): import sys print >>sys.stderr, 'WARNING: FillInProfile called with an email account' else: try: return GetInfo(acct, pref('infobox.showprofile', False)) except Exception: print_exc() return '' def memo_format(self, cachekey): if isinstance(cachekey, tuple): acct = cachekey[0] return format(self.format[acct.service][cachekey[1]], acct, self.htmlfonts) else: acct = cachekey return format(self.format[acct.service], acct, self.htmlfonts) def make_format(self, cachekey, obj = None, data = None): if isinstance(cachekey, tuple): acct = cachekey[0] else: acct = cachekey if acct.service not in ('digsby', 'facebook', 'myspace', 'twitter'): import warnings warnings.warn("Don't know how to make an infobox for %r" % acct) return _(u'No additional information') return self.memo_format(cachekey) def OnLinkClicked(self, event): href = event.GetLinkInfo().GetHref() should_not_hide = False if href == '#profile': setpref('infobox.showprofile', not pref('infobox.showprofile')) self.InfoSync() return None elif href.decode('url')[:3] == '^_^': href = href.decode('url') href = href[3:].split('/') fname = href.pop(0) args = href try: should_not_hide = getattr(self.account, fname)(*args) except Exception: e = None print_exc() except: None<EXCEPTION MATCH>Exception None<EXCEPTION MATCH>Exception wx.CallAfter(wx.LaunchDefaultBrowser, href) if pref('infobox.hide_on_click', True): if not should_not_hide: self.Hide() def Befriend(self, friend): self.friends.add(friend) def Defriend(self, friend): self.friends.discard(friend) def FriendlyTouch(self, mp = None): windowatpointer = FindWindowAtPointer() for friend in self.friends: if friend and windowatpointer is friend: if isinstance(friend, BuddyList): if not mp: pass None if not friend.ClientRect.Contains(friend.Parent.ScreenToClient(GetMousePosition())) and GetMouseState().LeftDown() else GetMouseState().LeftDown() return True continue return False from copy import deepcopy as copy from util import curly, get def format(fmt, obj, htmlfonts, data = None): if data is None: data = [] return_str = True else: return_str = False mysentinel = Sentinel() sget = lambda o, k: get(o, k, mysentinel) mydata = [] mydata_append = mydata.append order = get(fmt, 'order', fmt.keys()) curlylocals = copy(fmt) curlylocals['fonts'] = htmlfonts curlylocals['TagFont'] = TagFont for key in order: fmtval = sget(fmt, key) objval = sget(obj, key) if not objval and get(fmtval, 'hide_empty', False): continue if mysentinel in (fmtval, objval): continue continue if isinstance(objval, list): hdr = curly(get(fmtval, 'header', ''), source = curlylocals) sep = curly(get(fmtval, 'separator', ''), source = curlylocals) ftr = curly(get(fmtval, 'footer', ''), source = curlylocals) mydata.append(hdr) if not objval: curlylocals['obj'] = obj mydata_append(curly(get(fmtval, 'none', ''), source = curlylocals)) else: for thing in objval: type_d = get(fmtval, type(thing).__name__, { }) if not type_d: continue mydata_append(sep) mydata_append(make_icon_str(get(type_d, 'icon', ''))) curlylocals['obj'] = thing mesgstr = get(type_d, 'message', '') mydata_append(curly(mesgstr, source = curlylocals)) mydata_append(sep) mydata_append(ftr) continue if isinstance(fmtval, dict): format(fmtval, objval, htmlfonts, mydata) continue if not objval: continue curlylocals['obj'] = obj mydata_append(curly(fmtval, source = curlylocals)) if len(mydata) == 0: curlylocals['obj'] = obj mydata_append(curly(get(fmt, 'none', ''), source = curlylocals)) mydata = make_header(fmt, curlylocals) + mydata + make_footer(fmt, curlylocals) data.extend(mydata) if return_str: return ''.join(data) else: return data def make_icon_str(s): if not s: return '' s = s[5:] sent = object() return '<wxp module="gui.infobox.htmlbitmaps"class="BitmapFromSkin" width ="99%%" height="-1"><param name="key" value="%s"></wxp>' % s def make_header(fmt, obj): return [ curly(get(fmt, k, ''), source = obj) for k in ('header', 'separator') ] def make_footer(fmt, obj): return [ curly(get(fmt, k, ''), source = obj) for k in ('separator', 'footer') ] if 'wxMSW' in wx.PlatformInfo: from gui.native.win.winconstants import HWND_TOPMOST, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_SHOWWINDOW WINDOWPOS_FLAGS = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW from ctypes import windll SetWindowPos = windll.user32.SetWindowPos def show_on_top(win): SetWindowPos(win.Handle, HWND_TOPMOST, 0, 0, 0, 0, WINDOWPOS_FLAGS) import gui.input as gui gui.input.add_class_context(_('InfoBox'), 'InfoBox', cls = InfoBox)